package com.meraklisina.latexeditor.util;
 

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;

import com.meraklisina.latexeditor.mdi.TextEditor.TextEditors;

public class LatexWordCounter extends JPanel implements ActionListener
{

	private static final long serialVersionUID = 1L;
	/* Word count variables */
	private BufferedReader fileInput;	// Input file
	private File fileName;				// Idem
	private boolean latex;				// check if ".tex" extension in filename
	private String line;				// We read the file line by line
	private String word;				// Segmentation of line in words
	private String word2;				// Used when LaTeX command not finished in 1 word
	private int nbWords;				// Number of words already seen
	private int nbLatexCommands;		// Number of commands already seen
	private int nbBraces;				// Number of braces in LaTeX command
	private String [] includedFiles; 	// List of included files
	private short nbIncludedFiles;		// Number of included files
	private int nbWordsInIncludedFiles;	// Number of words in included files
	private String name;				// The name of the file
	private boolean firstFile;			// If the file is the first or included
	private String filePath;			// The path of the files (used for included files)
	private String logStr;				// String that keeps all logs from a file
	private boolean title;				// If the user want to count the title in the total
	private String chapter;				// The name of the chapter
	private short nbSections;			// The number of sections
	private String[] sections;			// The names of the sections
	private int[] sectionsWords;		// The number of words by sections
	private int nbChapter;				// The number of chapters
	private boolean chaptSect;
	

	/* GUI components */
	private JButton closeButton;
	private JLabel totalLabel;
	private JTextField totalTextField;
	private JDialog dialog;  //TG
	private JTabbedPane tab_Editors;  //TG
	
	/* Constructor for the first time */
	public LatexWordCounter(JDialog jd, JTabbedPane editors) {
		super();

		commonInit();

		/* Initialisation of variables */
		firstFile = true;
		title = false;

		/* Chapter count (-1 means no section count but file count) */
		nbChapter = -1;
		
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch(Exception e) {e.printStackTrace();}
		initGUI(jd, editors);
		
		this.filePath = new String ("");
	}

	/** Returns active JTextPane object
	 */
	public JTextPane getTextEditor()
	{
		return new TextEditors().GetJTextPaneAt(this.tab_Editors, this.tab_Editors.getSelectedIndex());
	}
	
	public LatexWordCounter(String filePath,JDialog jd, JTabbedPane editors) {
		this(jd, editors);				
		
		File tmp = new File (filePath);
		if (!tmp.exists())
			return;
		
		if (tmp.isDirectory())
			this.filePath = new String (filePath);
		else
		{			
			/* Get name */
			this.name = new String (filePath);
			this.fileName = tmp;
			if ((name.substring(name.length() - 4)).equals(".tex")) {
				latex = true;
			}
			else {
				latex = false;
			}
			
			/* Get path */
			int i = 0;
			while (i < name.length()+1 
					&& name.charAt(name.length() - i++ - 1) != File.separator.charAt(0)) {}
			this.filePath = name.substring(0,(name.length() - i + 1));
			
			/* Initialize count */
			nbWords = 0;
			nbLatexCommands = 0;
			nbIncludedFiles = 0;
			nbSections = 0;
			if (nbChapter != -1) 
				nbChapter = 0;
			nbWordsInIncludedFiles = 0;
			firstFile = true;			
			String printedTotal = Integer.toString(count().getInt());
			totalTextField.setText(printedTotal);
		}
	}
	
	
	/* Constructor for every included file */
	public LatexWordCounter (File name, String filePath, boolean title, int nbChapter) 
	{
		/* Initialisation of variables */
		firstFile = false;
		fileName = name;
		latex = true;
		this.name = new String (name.toString());
		this.filePath = new String (filePath);
		this.title = title;
		
		/* Chapter count */
		this.nbChapter = nbChapter;
		
		commonInit();
	}

	/* commonInit(): Init shared by the 2 constructor */
	private void commonInit() {
		/* Initialisation main variable */
		logStr = new String();
		nbWords = 0;
		nbLatexCommands = 0;
		
		/* included files */
		includedFiles = new String [100];
		nbIncludedFiles = 0;
		nbWordsInIncludedFiles = 0;
		
		/* chapter count */
		sections = new String [30];
		nbSections = 0;
		//nbWordsInSection = 0;
		sectionsWords = new int [30];
		
		/* chaptsect = false means uses of section and subsection for log 
		 * in the place of chapter and section
		 */
		chaptSect = false;
	}
	/* End of commonInit() */

	/* Initialisation of all GUI components */
	public void initGUI(JDialog dialog,JTabbedPane editors)
	{
		this.dialog = dialog;
		this.tab_Editors=editors;
		this.setFocusable(true);
		
		addKeyListener(new java.awt.event.KeyAdapter() {
			public void keyPressed(java.awt.event.KeyEvent evt) {
				formKeyPressed(evt);
			}
		});
		
		totalLabel = new JLabel("Total Words:");
		totalLabel.setName("totalWordsLabel");
		
		totalTextField = new JTextField("");
		totalTextField.setEditable(false);

		closeButton = new JButton("OK");
		closeButton.setName("OKButton");		

		closeButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				closeButtonActionPerformed(evt);
			}
		});

		GroupLayout layout = new GroupLayout(this);
		this.setLayout(layout);

		layout.setHorizontalGroup(
	            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	            .addGroup(layout.createSequentialGroup()
	                .addContainerGap()
	                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	                    .addGroup(layout.createSequentialGroup()
	                        .addComponent(totalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
	                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	                        .addComponent(totalTextField)
	                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	                        .addComponent(closeButton)
	                    ))
	                .addContainerGap())
	        );

	        layout.setVerticalGroup(
	            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	            .addGroup(layout.createSequentialGroup()
	                .addContainerGap()
	                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
	                    .addComponent(totalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
	                    .addComponent(totalTextField)
	                    .addComponent(closeButton))
	                .addContainerGap())
	        );

	}
	
	private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
		// TODO add your handling code here:
	}//GEN-LAST:event_formKeyPressed
	
	private void closeButtonActionPerformed(ActionEvent actionEvent) {//GEN-FIRST:event_BtnCancelActionPerformed
		this.dialog.setVisible(false);
	}
	
	/* actionPerformed(): When a menu item or a button is used */
	public void actionPerformed(ActionEvent event)
	{
		/* Count Button Handler */
		if(event.getSource() == closeButton)
		{
			if (name != null)
			{
				String printedTotal;
				nbWords = 0;
				nbLatexCommands = 0;
				nbIncludedFiles = 0;
				nbWordsInIncludedFiles = 0;
				nbSections = 0;
				if (nbChapter != -1) nbChapter = 0;
				firstFile = true;
				printedTotal = Integer.toString(count().getInt());
				totalTextField.setText(printedTotal);
			}
			else
			{
				JOptionPane.showMessageDialog
					(this,"No Opened File ", "Error: ",JOptionPane.ERROR_MESSAGE);
			}
		} 
	}

	/* count(): count the number of word in the file */
    private strInt count()
    {
		int i, j, k;
		int nbWordsInSection = 0;
		char [] wordTab;
		char [] wordTab2;
	
        /* Open the file */
		if (openFile() == -1) {
			logStr += name.substring(filePath.length(), name.length()) +": File does not exist\n";
			return new strInt(0, logStr, nbChapter);
		}
		
		try
		{
			while ((line = fileInput.readLine()) != null)
			{		
				i = 0;

				/* Get rid of all spaces */
				while ((i < line.length()) && (line.charAt(i) == ' ')) {i++;}

				while (i < line.length())
				{
					j = 0;
					wordTab = new char [200];

					/* Extract the next word */
					while ((i < line.length()) && (line.charAt(i) != ' ') && (line.charAt(i) != '\'')) {
						wordTab[j++] = line.charAt(i++);
					}

					/* Getting rid of following space */
					while ((++i < line.length()) && (line.charAt(i) == ' ')) {}

					/* If LaTeX command */
					if ((latex) && (wordTab[0] == '\\'
						|| (wordTab[0] == '{' && wordTab[1] == '\\')
						|| wordTab[0] == '%')
						|| wordTab[0] == '&')
					{
						if ((wordTab[0] == '\\') 
							&& (!(new String (wordTab).substring(0, 5).equals("\\item")))
							&& (!(new String (wordTab).substring(0, 5).equals("\\fbox")))
							&& (!(new String (wordTab).substring(0, 10).equals("\\resizebox"))))
						{
							/* If it is a command, we check that we have all arguments */
							if ((i < line.length()) && (line.charAt(i) == '{'))
							{
								nbBraces = 1;
								i++;
								wordTab[j++] = ' ';
								wordTab[j++] = '{';
								while ((i < line.length()) && (nbBraces > 0))
								{
									if (line.charAt(i) == '{') nbBraces++;
									else if (line.charAt(i) == '}') nbBraces--;
									wordTab[j++] = line.charAt(i++);
								}
							}

							/* Copy the word */
							wordTab2 = new char [j];
							for (k = 0; k < j; k++)
								wordTab2[k] = wordTab[k];
							word = new String (wordTab2);
							
							/* Count the number of braces in the command */
							nbBraces = 0;
							for (k = 0; k < j; k++) {
								if (word.charAt(k) == '{') nbBraces++;
								else if (word.charAt(k) == '}') nbBraces--;
							}

							/* If the command is not closed yet, taking the next word */
							while (nbBraces > 0)
							{
								wordTab = new char [100];
								j = 0;

								/* Extract the next word */
								while ((i < line.length()) && (line.charAt(i) != ' ')) {
									wordTab[j++] = line.charAt(i++);
								}

								/* Getting rid of following space */
								while ((i < line.length()) && (line.charAt(i) == ' ')) {i++;}

								/* Read new line if necessary */
								if (i == line.length() && ((line = fileInput.readLine()) != null))
								{			
									i = 0;

									/* Get rid of all spaces */
									while ((i < line.length()) && (line.charAt(i) == ' ')) {i++;}
								}

								/* Copy the word, and ajust braces count */
								wordTab2 = new char [j];
								for (k = 0; k < j; k++)
									wordTab2[k] = wordTab[k];
								word2 = new String (wordTab2);
								
								for (k = 0; k < j; k++) {
									if (word2.charAt(k) == '{') nbBraces++;
									else if (word2.charAt(k) == '}') nbBraces--;
								}

								/* Concat the 2 words */
								word = word.concat(" ");
								word = word.concat(word2);
								
								if (line == null)
								{
									return new strInt((nbWords + nbWordsInIncludedFiles), logStr, nbChapter);
								}
							}

							/* Check if command is \include{}. or \input{}
							 * If yes, the file included is also readed.
							 */

							String command = extractCommand(word);

							if (command.equals("\\include") || command.equals("\\input"))
							{
								if (command.equals("\\include"))
									includedFiles[nbIncludedFiles++] = new String (word.substring(9,word.length()-1) + ".tex");
								else
									includedFiles[nbIncludedFiles++] = new String (word.substring(7,word.length()-1) + ".tex");
							}
							else
							{
								/* Recording the name if [count by section] */
								if (nbChapter >= 0)
								{
									if (command.equals("\\chapter") 
										|| ((! chaptSect) && (command.equals("\\section"))))
									{
										String chapterName;
										int l, m;
										nbChapter++;
										
										if (command.equals("\\chapter")) 
											chaptSect = true;

										/* First extract any label command */
										m = command.length();
										l = m + 1;
										m = (word.charAt(m+1) == '{') ? m+2 : m+1;

										while ((l < word.length()) 
														&& ((word.charAt(l) != '\\') || (word.charAt(l+1) == '&')) 
														&& (word.charAt(l) != '}')) {
											l++;
										}
										
										if ((l < word.length()) && (word.charAt(l) != '}'))
										{
											chapterName = new String (word.substring(m, l));

											while ((l < word.length()) && (word.charAt(l++) != '}')) {}
											if (l < word.length()) 
												chapter = 
													chapterName.concat(word.substring(l, word.length()-1));
										}
										else chapter = new String (word.substring(m, word.length()-1));
										}
									else if ((command.equals("\\section")) 
										|| ((! chaptSect) && (command.equals("\\subsection"))))
									{
										String sectionName;
										int l, m;
										
										sectionsWords[nbSections] = nbWordsInSection;
										nbWordsInSection = 0;

										/* Extract any label in the word */
										m = command.length();
										l = m + 1;
										m = (word.charAt(m+1) == '{') ? m+2 : m+1;

										while ((l < word.length()) 
														&& ((word.charAt(l) != '\\') || (word.charAt(l+1) == '&')) 
														&& word.charAt(l) != '}') {
											l++;
										}
										if ((l < word.length()) && (word.charAt(l) != '}'))
										{
											sectionName = new String (word.substring(m, l));

											while ((l < word.length()) && (word.charAt(l++) != '}')) {}
											if (l < word.length())
												sections[++nbSections] = 
													sectionName.concat(word.substring(l, word.length()-1));
										}
										else sections[++nbSections] = 
											new String (word.substring(m, word.length()-1));
									}
								}

								/* Checking if user want to count the titles */
								if (title)
								{
									if (command.equals("\\chapter")
										|| command.equals("\\section")
										|| command.equals("\\subsection")
										|| command.equals("\\subsubsection")
										|| command.equals("\\paragraph")
										|| command.equals("\\subparagraph"))
									{
										/* Counting the words of the title */
										k = command.length() + 1;
										j = 0;

										while (k < word.length())
										{
											/* Extract the next word */
											while ((k < word.length()) 
															&& (word.charAt(k) != ' ') 
															&& (word.charAt(k) != '\'')) {
												wordTab[j++] = word.charAt(k++);
											}

											/* Getting rid of following space */
											while ((++k < word.length()) && (word.charAt(k) == ' ')) {}

											/* Add a word */
											nbWords++;
										}
									}
								}
								nbLatexCommands++;
							}
						}
						else if (wordTab[0] == '{' && wordTab[1] == '\\') {
							wordTab2 = new char [j];
							for (k = 0; k < j; k++)
								wordTab2[k] = wordTab[k];
							word = new String (wordTab2);
							nbLatexCommands++;
						}
						else  if (wordTab[0] == '%') /* -> comment */
						{
							if ((line = fileInput.readLine()) == null)
							{
								return new strInt((nbWords + nbWordsInIncludedFiles), 
																logStr, nbChapter);
							}
							
							i = 0;

							/* Get rid of all spaces */
							while ((i < line.length()) && (line.charAt(i) == ' ')) {i++;}
						}
					}
					else {
						/* Compare word with documentclass */
						word = new String (wordTab);
						word = word.substring (0, 13);
						word2 = "documentclass";
						if (word.compareTo(word2) != 0)
						{													
							/* Add a word */
							nbWords++;
							nbWordsInSection++;
						}
					}
				}
			}
			
			/* Close the file */
			closeFile();
			
		}
		catch(IOException ioException)
		{		
			JOptionPane.showMessageDialog(this,"Error reading File:\n" +
				name.substring(filePath.length() ,name.length()),
				"Error: ",JOptionPane.ERROR_MESSAGE);
			closeFile();
			System.exit(1);
		}

		return new strInt((nbWords + nbWordsInIncludedFiles), logStr, nbChapter);
    }
	/* End of count() */
	
	/* extractCommand(): Get the command out of a command String */
	private String extractCommand (String command)
	{
		int l = 0;

		while ((++l < command.length()) 
					&& (command.charAt(l) != '{') 
					&& (command.charAt(l) != ' ')) {}

		return command.substring(0,l);
	}
	/* end of extractCommand() */

	/* openFile(): Opening the file */
    private int openFile()
    {
		try
		{
			FileReader file = new FileReader(fileName);
			fileInput = new BufferedReader(file);
		}
		catch(IOException ioException)
		{
			JOptionPane.showMessageDialog
				(this,"Error Opening File: \n" +
					name.substring(filePath.length() ,name.length()),
					"Error: ",JOptionPane.ERROR_MESSAGE);

			return -1;
		}
		return 0;
	}
	/* End of OpenFile() */

	/* closeFile(): Closing the file */
	private void closeFile()
    {
        if (fileInput != null)
		{
	    	try	{ fileInput.close(); }
	   	 	catch (IOException ioException)
	    	{
	        	JOptionPane.showMessageDialog
	        		(this,"Error Closing File", "Error: ",
	        		JOptionPane.ERROR_MESSAGE);
	    	}
		}
    }
    /* End of closeFile() */
    /* End of file handling methods */

//    public static void main(String[] args)
//    {
//		LatexWordCounter wordc;
//				
//		if (args.length == 0)
//			wordc = new LatexWordCounter ();
//		else
//			wordc = new LatexWordCounter (args[0]);
//	}
}



